#include "LightingCommon.fxh"

cbuffer cbPerFrame
{
	float4x4 gProj;
};

cbuffer cbPerLight
{
	float4x4 gWorldView;
	float3 gLightPosV;
	float4 gLightColorAndIntens;
	float2 gLightRadiusAndFalloff;
};

struct VS_IN
{
	float3 posL     : POSITION;
};

struct VS_OUT
{
	float4 posD         : SV_POSITION;
	float3 viewRayV     : TEXCOORD1;
};

struct PS_IN
{
	float4 posD         : SV_POSITION;
	float3 viewRayV     : TEXCOORD1;
#ifdef MSAA
	uint sampleIndex : SV_SAMPLEINDEX;
#endif
};

VS_OUT VS(VS_IN vIn)
{
	VS_OUT vOut;

	float4 posV = mul(float4(vIn.posL, 1.0f), gWorldView);
	float4 posH = mul(posV, gProj);

	vOut.posD = posH;

	// view space vertex position is the same thing as view ray in view space
	vOut.viewRayV = posV.xyz;
	
	return vOut;
}

float4 PS(PS_IN pIn) : SV_Target
{
	float3 viewRayV = normalize(pIn.viewRayV);
	
	int3 texCoord = int3(pIn.posD.xy, 0);
	float3 normalV, diffColor;
	float specIntens, specPower;
#ifdef MSAA
	float3 posV = viewRayV * getDepthFromGBufferLoadMS(pIn.sampleIndex, texCoord);
	getPixelParamsFromGBufferLoadMS(pIn.sampleIndex, texCoord, normalV, diffColor, specIntens, specPower);
#else
	float3 posV = viewRayV * getDepthFromGBufferLoad(texCoord);
	getPixelParamsFromGBufferLoad(texCoord, normalV, diffColor, specIntens, specPower);
#endif
	
	float3 lightDirV = gLightPosV - posV;
	float lightDist = length(lightDirV);
	lightDirV = normalize(lightDirV);

	float lightRadius = gLightRadiusAndFalloff.x;
	float atten = saturate((lightRadius - lightDist) / lightRadius);

	float3 lighting = calculateLighting(viewRayV, lightDirV, normalV, gLightColorAndIntens, diffColor, specIntens, specPower);

	return float4(atten * lighting, 1.0f);
}


technique11 tech
{
	pass P0
	{
		SetVertexShader( CompileShader( vs_5_0, VS() ) );
		SetGeometryShader( NULL );
		SetPixelShader( CompileShader( ps_5_0, PS() ) );
		
		SetDepthStencilState(DepthOff, 0);
		SetBlendState(Additive, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF);

#ifdef MSAA
		SetRasterizerState(CullFrontMS);
#else
		SetRasterizerState(CullFront);
#endif
	}
}
